package com.huo.common;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

import org.apache.log4j.Logger;


/**
 * <p>Title: Convert Tool</p>
 * <p>Description: Convert Tool</p>
 * @author Huoyan
 * @version 1.0
 * <p>Company: </p>
 * <p>Copyright 2011</p>
 */
public class Convert {
	
	private static Logger log = Logger.getLogger(Convert.class);
	private static String hexDigital="0123456789ABCDEF";
	private final static String SEPARATIVE_SIGN_STRING = " ";//String space
	private final static char SEPARATIVE_SIGN_CHAR = ' ';
	
	public static String UTF8 = "UTF-8";
	public static String GBK = "GBK";
	
	/**
	 * utf8 to GBK
	 * @param s
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String utf8ToGbk(String s) throws UnsupportedEncodingException{
		return new String(s.getBytes("GBK"), "GBK");
	}
	
	/**
	 * ANSI conversion utf8 code
	 * @param ansistr
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static byte[] ansi2utf8(String ansistr) throws UnsupportedEncodingException {
		char c[] = ansistr.toCharArray();
		byte[] fullByte = new byte[3 * c.length];
		byte[] rebyte = null;
		int reindex = 0;
		for (int i = 0; i < c.length; i++) {
			if (c[i] > 0x80) {
				int m = (int) c[i];
				String word = Integer.toBinaryString(m);
				StringBuffer sb = new StringBuffer();
				int len = 16 - word.length();
				for (int j = 0; j < len; j++) {
					sb.append('0');
				}
				sb.append(word);
				sb.insert(0, "1110");
				sb.insert(8, "10");
				sb.insert(16, "10");
				fullByte[reindex] = Integer.valueOf(sb.substring(0, 8), 2).byteValue();
				fullByte[reindex + 1] = Integer.valueOf(sb.substring(8, 16), 2).byteValue();
				fullByte[reindex + 2] = Integer.valueOf(sb.substring(16), 2).byteValue();
				reindex += 3;
			} else {
				//byte[] b= Convert.toBytes(new char[]{c[i]});
				byte b = (byte)c[i];
				fullByte[reindex] = b;//b[0];
				reindex++;
			}
		}
		rebyte = new byte[reindex];
		for(int i=0;i<reindex;i++){
			rebyte[i] = fullByte[i];
		}
		return rebyte;
	}
	
	/**
	 * The text into 16 hexadecimal space delimited string(Take the 16 hexadecimal QQNumber)
	 * @param s s is a long number for example qqnumber
	 * @return
	 */
	public static String getHexString(String s){
		return getHexString(Convert.toLong(s));
	}
	
	/**
	 * The text into 16 hexadecimal space delimited string(Take the 16 hexadecimal QQNumber)
	 * @param l l is a long number for example qqnumber
	 * @return
	 */
	public static String getHexString(long l){
		//String nkg = null;
		//byte[] numText7;
		//numText7 = Convert.toByteArray(Convert.toLong(number));
		//nkg = String.format("%02x %02x %02x %02x", numText7[3],numText7[2],numText7[1],numText7[0]);
		StringBuffer sb = new StringBuffer(Long.toHexString(l));
		char c = SEPARATIVE_SIGN_CHAR;
		if(sb.length() > 8){
			sb.delete(0, sb.length()-8);
		}else{
			for (int i = sb.length(); i < 8; i++) {
				sb.insert(0, '0');
			}
		}
		sb.insert(2, c);
		sb.insert(5, c);
		sb.insert(8, c);
		sb.insert(sb.length(), c);
		return sb.toString();
	}
	
	/**
	 * The string is encoded into hex digits, 
	 * applies to all characters ( including Chinese )
	 * @param s
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static String toHexString(String s) throws UnsupportedEncodingException{
		return toHexString(s, Convert.GBK, true);
	}
	
	/**
	 * The specify string is encoded into hex digits, 
	 * applies to all characters ( including Chinese )
	 * @param s  To convert string
	 * @param encode  string encoding default GBK
	 * @param isSpaceSplit
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String toHexString(String s, boolean isSpaceSplit) throws UnsupportedEncodingException{
		return toHexString(s.getBytes(), isSpaceSplit);
	}
	
	/**
	 * The specify string is encoded into hex digits, 
	 * applies to all characters ( including Chinese )
	 * @param s  To convert string
	 * @param encode  string encoding default GBK
	 * @param isSpaceSplit
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String toHexString(String s, String encode, boolean isSpaceSplit) throws UnsupportedEncodingException{
		return toHexString(s.getBytes(encode), isSpaceSplit);
	}
	
	/**
	 * The bytes is encoded into hex digits, 
	 * applies to all characters ( including Chinese )
	 * @param bytes
	 * @param isSpaceSplit
	 * @return
	 */
	public static String toHexString(byte[] bytes, boolean isSpaceSplit){
		StringBuffer sb = new StringBuffer(bytes.length * 2);
		// The array of bytes in each byte is divided into 2 Hex
		for (int i = 0; i < bytes.length; i++) {
			sb.append(hexDigital.charAt((bytes[i] & 0xf0) >> 4));
			sb.append(hexDigital.charAt((bytes[i] & 0x0f) >> 0));
		}
		if(isSpaceSplit)
			return setHexStringSplit(sb.toString(), SEPARATIVE_SIGN_STRING);
		else
			return sb.toString();
	}
	
	/**
	 * Make a byte is encoded into hex string
	 * @param b
	 * @return
	 */
	public static String toHexString(byte b) {
		StringBuffer hexstr = new StringBuffer(Integer.toHexString(b));
		int m = hexstr.length();
		if (m < 2) {
			hexstr.insert(0, '0');
		} else {
			hexstr.delete(0, m - 2);
		}
		return hexstr.toString();
	}
	
	/**
	 * Hex digits decoded into a string, 
	 * applies to all characters ( including Chinese )
	 * @param hex
	 * @param encode string Code like utf8 or gbk or other
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String toString(String hex, String encode) throws UnsupportedEncodingException{
		char[] hex2char = hex.toCharArray();
        byte[] bytes = new byte[hex.length() / 2];
        int temp;
        for (int i = 0; i < bytes.length; i++) {
            temp = hexDigital.indexOf(hex2char[2 * i]) * 16;
            temp += hexDigital.indexOf(hex2char[2 * i + 1]);
            bytes[i] = (byte) (temp & 0xff);
        }
        return new String(bytes, encode);
	}
	
	/**
	 * Parses the the specified array of bytes argument as a long
	 * @param b
	 * @return
	 */
	public static long toLong(byte[] b) {
		long s = 0;
		long s0 = b[0] & 0xff;
		long s1 = b[1] & 0xff;
		long s2 = b[2] & 0xff;
		long s3 = b[3] & 0xff;
		long s4 = b[4] & 0xff;
		long s5 = b[5] & 0xff;
		long s6 = b[6] & 0xff;
		long s7 = b[7] & 0xff;
		s1 <<= 8;
		s2 <<= 16;
		s3 <<= 24;
		s4 <<= 8 * 4;
		s5 <<= 8 * 5;
		s6 <<= 8 * 6;
		s7 <<= 8 * 7;
		s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
		return s;
	}
	
	/**
	 * Parses the long argument as array of bytes
	 * @param number
	 * @return
	 */
	public static byte[] toBytes(long number) {
		long temp = number;
		byte[] b = new byte[8];
		for (int i = 0; i < b.length; i++) {
			b[i] = new Long(temp & 0xff).byteValue();
			temp = temp >> 8;
		}
		return b;
	}
	
	/**
	 * Parses the int argument as array of bytes
	 * @param v
	 * @return
	 */
	public static byte[] toBytes(int v) {
		byte[] result = new byte[4];
		result[0] = (byte) (v & 0xFF);
		result[1] = (byte) ((v >> 8) & 0xFF);
		result[2] = (byte) ((v >> 16) & 0xFF);
		result[3] = (byte) ((v >> 24) & 0xFF);
		return result;
	}
	
	/**
	 * Parses the hex String argument as array of bytes
	 * @param hexstr
	 * @return
	 */
	public static byte[] toBytes(String hexstr) {
		StringBuffer s = null;
		if(hexstr.indexOf(" ") > 0 ){
			//s = new StringBuffer(hexstr.replaceAll(" ", ""));
			s = new StringBuffer(delHexStringSplit(hexstr, SEPARATIVE_SIGN_STRING));
		}else{
			s = new StringBuffer(hexstr);
		}
		byte[] b = new byte[s.length() / 2];
		for (int i = 0; i < b.length; i++) {
			b[i] = (byte) (Integer.parseInt(s.substring(0, 2), 16));
			s.delete(0, 2);
		}
		return b;
	}
	
	/**
	 * Parses the Array Of Char argument as array of bytes
	 * @param chars
	 * @return
	 */
	public static byte[] toBytes(char[] chars) {
		Charset cs = Charset.forName("UTF-8");
		CharBuffer cb = CharBuffer.allocate(chars.length);
		cb.put(chars);
		cb.flip();
		ByteBuffer bb = cs.encode(cb);
		return bb.array();
	}
	
	/**
	 * Parses the array of bytes argument as Array Of Char
	 * @param bytes
	 * @return
	 */
	public static char[] toChars(byte[] bytes) {
		Charset cs = Charset.forName("UTF-8");
		ByteBuffer bb = ByteBuffer.allocate(bytes.length);
		bb.put(bytes);
		bb.flip();
		CharBuffer cb = cs.decode(bb);
		return cb.array();
	}
	
	/**
	 * Convert byte to int
	 * @param b
	 * @return
	 */
	public static int toInt(byte b) {
		return (int) b & 0xFF;
	}
	
	/**
	 * Convert char to int
	 * @param c
	 * @return
	 */
	public static int toInt(char c) {
		if (c >= 'a')
			return (c - 'a' + 10) & 0x0f;
		if (c >= 'A')
			return (c - 'A' + 10) & 0x0f;
		return (c - '0') & 0x0f;
	}
	 
	/**
	 * Parses the the specified array of bytes argument as a int
	 * @param v
	 * @param offset
	 * @return
	 */
	public static int toInt(byte[] v, int offset){
		if(offset + 4 > v.length) return 0;
		int output;
		output = (int)v[offset];
		output |= (int)(v[offset + 1] << 8);
		output |= (int)(v[offset + 2] << 16);
		output |= (int)(v[offset + 3] << 24);
		return output;
	}
	
	/**
	 * Convert String to int
	 * @param
	 * @return
	 */
	public static int toInt(String s){
		int i = 0; 
		if(StringUtil.isBlank(s)){
			s="0";
		}
		try {
			i = Integer.parseInt(s);
		} catch (Exception e) {
			log.error("ת�ʹ���: ��Stringת��Ϊintʱ��?String="+s);
			e.printStackTrace();
		}
		return i;
	}
	
	/**
	 * Sixteen hex convert to decimal
	 * @param s
	 * @param radix
	 * @return
	 */
	public static int toInt(String hexstr, int radix){
		return Integer.parseInt(hexstr, radix);
	}
	
	/**
	 * Convert String to double
	 * @param
	 * @return
	 */
	public static double toDouble(String s){
		double d = 0.0;
		if(StringUtil.isBlank(s)){
			s="0.0";
		}
		try {
			d = Double.parseDouble(s);
		} catch (Exception e) {
			log.error("ת�ʹ���: ��Stringת��Ϊdoubleʱ��?String="+s);
			e.printStackTrace();
		}
		return d;
	}
	
	/**
	 * Convert String to Long
	 * @param s ��ת�͵�String
	 * @return longת�ͺ���
	 */
	public static long toLong(String s){
		long l = 0;
		if(StringUtil.isBlank(s)){
			s="0";
		}
		try {
			l = Long.parseLong(s);
		} catch (Exception e) {
			log.error("ת�ʹ���: ��Stringת��Ϊlongʱ��?String="+s);
			e.printStackTrace();
		}
		return l;
	}
	
	/**
	 * Delete split string in hex string 
	 * @param hexstr
	 * @param split
	 * @return
	 */
	private static String delHexStringSplit(String hexstr, String split){
		StringBuffer s = new StringBuffer(hexstr);
		for (int i = 0; i < s.length(); i++) {
			//System.out.println(s.toString());
			int n = s.indexOf(split);
			if (n > 0) s.deleteCharAt(n);
			else break;
		}
		return s.toString();
	}
	
	/**
	 * Insert split string in hex string
	 * @param hexstr
	 * @param split
	 * @return
	 */
	public static String setHexStringSplit(String hexstr, String split){
		StringBuffer newstr = new StringBuffer(delHexStringSplit(hexstr,SEPARATIVE_SIGN_STRING));
		int len = newstr.length();
		int j = 2;
		for (int i = 0; i < len / 2; i++) {
			newstr.insert(j, split);
			j = j + split.length() + 2;
		}
		return newstr.toString();
	}
}
